package com.tanhua.server.service;

import com.tanhua.commons.template.OssTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mogo.Comment;
import com.tanhua.domain.mogo.Publish;
import com.tanhua.domain.mogo.Visitor;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVO;
import com.tanhua.domain.vo.VisitorVO;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.PublishApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.util.RelativeDateFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class MovementsService {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Reference
    private VisitorApi visitorApi;
    @Reference
    private CommentApi commentApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private PublishApi publishApi;
    @Autowired
    private  MovementsMQService movementsMQService;
    /**
     * 查询  给当前用户推荐的动态列表
     *
     * @param page     页码
     * @param pagesize 查询几条
     */
    public ResponseEntity recommendPublishList(int page, int pagesize) {
        //1.获取用户
        User user = UserHolder.getUser();
        //优先从redis中查询大数据推荐的动态
        PageResult<Publish> pageResult=fingRecommendFromRedis(page,pagesize);
        if (pageResult==null){
            pageResult=publishApi.findByTimeline(page,pagesize,user.getId());

        }

        //2.查询当前用户推荐的动态
        List<Publish> publishList = pageResult.getItems();
        //3.把每条动态信息，转换成publicVO
        List<PublishVO> voList = new ArrayList<>();
        for (Publish publish : publishList) {
            PublishVO vo = new PublishVO();
            //查询动态的发布人信息，封装到vo对象
            //3.1发布人的详细信息
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            BeanUtils.copyProperties(userInfo,vo);
                vo.setTags(userInfo.getTags().split(","));
            //3.2动态信息
            //把Publish封装到vo对象
            BeanUtils.copyProperties(publish,vo);
            vo.setId(publish.getId().toHexString());
            vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            //当前用户是否点赞了这条动态
            Boolean isLike = redisTemplate.hasKey("publish_comment_like_" + user.getId() + "_" + publish.getId().toHexString());
            vo.setHasLiked(isLike?1:0);
            Boolean isLove = redisTemplate.hasKey("public_comment_love_" + user.getId() + "_" + publish.getId().toHexString());
            vo.setHasLoved(isLove?1:0);
            vo.setImageContent(publish.getMedias().toArray(new String[]{}));
            vo.setDistance("50米");
            //加入voList
            voList.add(vo);
        }
        //转换成PublicVo的分页对象
        PageResult<PublishVO> voPageResult = new PageResult<>();
        BeanUtils.copyProperties(pageResult,voPageResult);
        voPageResult.setItems(voList);
        log.debug("给用户{}推荐的动态VO：{}", user.getId(), voPageResult);
        return ResponseEntity.ok(voPageResult);

    }

    private PageResult<Publish> fingRecommendFromRedis(int page, int pagesize) {
        //先从redis中获取数据
        String pidStr = redisTemplate.opsForValue().get("QUANZI_PUBLISH_RECOMMEND_" + UserHolder.getUserId());
        if (pidStr==null){
            return null;
        }
        //查询推荐动态的总数量
        String[] pidArray = pidStr.split(",");
        int count=pidArray.length;
        //计算分了几页
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        //查询某一页的动态
        if (page<=pages){
            int start=(page-1)*pagesize;
            int end=start+pagesize;
            if (end>count){
                end=count;
            }
            List<Long> pidList = new ArrayList<>();
            for (int i=start;i<end;i++){
                long pid = Long.parseLong(pidArray[i]);
                pidList.add(pid);
            }
       List<Publish> publishList  = publishApi.findPublishListByPids(pidList);
            return new PageResult<>(count,pagesize,pages,page,publishList);
        }
        return new PageResult<>();
    }

    //发布动态
    public ResponseEntity publish(Publish publish, MultipartFile[] imageContent) throws IOException {
        // 1.把图片上传到阿里云Oss
        List<String> mediaList = new ArrayList<>();
        if (imageContent != null && imageContent.length > 0) {

            for (MultipartFile file : imageContent) {
                String path = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                mediaList.add(path);
            }
        }
        //2.把媒体图片路径设置到publis中
        publish.setMedias(mediaList);
        publish.setUserId(UserHolder.getUserId());
        publish.setSeeType(1);
        //待审核
        publish.setState(0);

        //调用api 保存动态数据
        String publishId = publishApi.save(publish);

        //发送消息
       rocketMQTemplate.convertAndSend("tanhua-public",publishId);
       movementsMQService.savePublishMessage(publishId);
        return ResponseEntity.ok(null);

    }
//好友动态

    public ResponseEntity friendPublishList(int page, int pagesize) {
        //获取当前用户iD
        Long userId = UserHolder.getUserId();
        //获取当前用户的好友动态列表（当前用户的时间线，是好友发布的动态列表）
        PageResult<Publish> publishPageResult = publishApi.findByTimeline(page, pagesize, userId);
        //转换成PublicVO
        List<PublishVO> voList = new ArrayList<>();
        for (Publish publish : publishPageResult.getItems()) {
            PublishVO vo = new PublishVO();
            vo.setId(publish.getId().toHexString());
            //查询发布人的信息 封装到vo里
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            BeanUtils.copyProperties(userInfo,vo);
            if (userInfo.getTags()!=null){
                vo.setTags(userInfo.getTags().split(","));

            }
            //把Public信息 封装到vo里
            BeanUtils.copyProperties(publish,vo);
            vo.setId(publish.getId().toHexString());
            vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            //当前用户是否点赞了 这条动态
            Boolean isLove = redisTemplate.hasKey("public_comment_like_" + userId + "_" + publish.getId().toHexString());
            vo.setHasLoved(isLove?1:0);
            vo.setImageContent(publish.getMedias().toArray(new String[]{}));
            vo.setDistance("50米");
            //把vo添加到voList里
            voList.add(vo);

        }
        //转换成vo的分页信息对象
        PageResult<PublishVO> voPageResult = new PageResult<>();
        BeanUtils.copyProperties(publishPageResult,voPageResult);
        voPageResult.setItems(voList);
        return ResponseEntity.ok(voPageResult);
    }

    //我的-我的动态（我的相册）
    public ResponseEntity albumPublishList(int page, int pagesize, Long userId) {
        if (userId==null){
            userId=UserHolder.getUserId();
        }
        //1\查询userId对应的相册
        PageResult<Publish> publishPageResult = publishApi.findAlbumList(page, pagesize, userId);
        //2.把每个publish转换成publishvo
        List<Publish> publishList = publishPageResult.getItems();
        ArrayList<PublishVO> publishVo = new ArrayList<>();
        for (Publish publish : publishList) {
            PublishVO vo = new PublishVO();
            vo.setId(publish.getId().toHexString());
            //把发布人信息封装进去
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            BeanUtils.copyProperties(userInfo,vo);
            if (userInfo.getTags()!=null){
                vo.setTags(userInfo.getTags().split(","));
            }
            //把动态信息封装进去
            BeanUtils.copyProperties(publish,vo);
            vo.setImageContent(publish.getMedias().toArray(new String[]{}));
            vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            vo.setDistance("50米");
            //当前用户是否点赞了这条动态
            Boolean isLike = redisTemplate.hasKey("publish_comment_like_" + userId + "_" + publish.getId().toHexString());
            vo.setHasLiked(isLike?1:0);
            //当前用户是否喜欢这条动态
            Boolean isLove = redisTemplate.hasKey("publish_comment_love_" + userId + "_" + publish.getId().toHexString());
            vo.setHasLoved(isLove?1:0);
            publishVo.add(vo);
        }
          //封装返回值
        PageResult<PublishVO> voPageResult = new PageResult<>();
         BeanUtils.copyProperties(publishPageResult,voPageResult);
          voPageResult.setItems(publishVo);
          return ResponseEntity.ok(voPageResult);


    }
//动态--点赞
    public ResponseEntity like(String publishId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //封装评论对象信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //评论类型 1 点赞  2评论 3喜欢
        comment.setCommentType(1);
        //   评论内容：1对动态评论，2对视频评论，3对评论评论
        comment.setPubType(1);


        //设置被评论的用户
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());


        //保存评论 得到点赞总数
        long count = commentApi.save(comment);

        //当前用户赞了 记录到redis里
        redisTemplate.opsForValue().set("publish_like_"+userId+"_"+publishId,"1");
        //发送消息
        movementsMQService.savePublishMessage(publishId);

        return ResponseEntity.ok(count);
    }
//动态-取消点赞
    public ResponseEntity dislike(String publishId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //删除点赞信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //   评论类型：1点赞，2评论，3喜欢
        comment.setCommentType(1);
        //删除点赞信息
        long count = commentApi.remove(comment);
        //当用户取消点赞了 从redis里删除记录
        redisTemplate.delete("publish_like_"+userId+"_"+publishId);
        //发送消息
        movementsMQService.savePublishMessage(publishId);


        return ResponseEntity.ok(count);
    }
 //动态-喜欢
    public ResponseEntity love(String publishId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //封装信息对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        comment.setCommentType(3);
        //   评论内容：1对动态评论，2对视频评论，3对评论评论
        comment.setPubType(1);
        //设置被评论的用户
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());
        long count = commentApi.save(comment);
        //当前用户喜欢了 存到redis里
        redisTemplate.opsForValue().set("publish_love_"+userId+"_"+publishId,"1");


        return ResponseEntity.ok(count);
    }

    //动态-取消喜欢
    public ResponseEntity unlove(String publishId) {
        //获取用户id
        Long userId = UserHolder.getUserId();
        //封装条件信息对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        comment.setCommentType(3);
        //删除
        long count = commentApi.remove(comment);
        //删除redis里的数据
        redisTemplate.delete("publish_love_"+userId+"_"+publishId);

        return   ResponseEntity.ok(count);
    }
//动态-查询单条动态（跳转到评论界面时，需要显示动态内容）
    public ResponseEntity findOnePublish(String publishId) {
        //查询publishId对应的动态
        Publish publish = publishApi.findById(publishId);

        //把结果转换成Publishvo
        PublishVO vo = new PublishVO();

        //2.1 把动态的发布人信息封装到vo里
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        BeanUtils.copyProperties(userInfo,vo);
        if (userInfo.getTags()!=null){
            vo.setTags(userInfo.getTags().split(","));
        }
        //把动态信息封装到vo里
        BeanUtils.copyProperties(publish,vo);
        vo.setId(publish.getId().toHexString());
        vo.setImageContent(publish.getMedias().toArray(new String[]{}));
        vo.setDistance("50米");
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
        //2.3 当前用户对此动态是否点赞了 是否喜欢了
        Boolean isLike = redisTemplate.hasKey("publish_like_" + UserHolder.getUserId() + "_" + publish.getId().toHexString());
        vo.setHasLiked(isLike?1:0);
        Boolean isLove = redisTemplate.hasKey("publish_love_" + UserHolder.getUserId() + "_" + publish.getId().toHexString());

        vo.setHasLoved(isLove?1:0);
        return ResponseEntity.ok(vo);
    }

    /* 首页--- 谁看过我*/
    //查询来访者
    public ResponseEntity findVisitorList() {
        //获取当前用户
        User user = UserHolder.getUser();
        //查找来访记录
        //2.1先从redis里查找 上次查看访问记录的时间
        String time = redisTemplate.opsForValue().get("visitor_time_" + user.getId());
        List<Visitor> visitorList=null;
        if (time!=null){ // 改成！=null
            //没有查看过访问记录 从mongoDB里查询前5条访问记录
            // ￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥
            // ########################兄弟  time都为空了  还要Long.valueOf呢？##############################
             visitorList = visitorApi.findVisitorListByStartDate(user.getId(), Long.valueOf(time));
             // ￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥￥

        }else {
            //0. 如果time为空的话，从数据库查询5条
            visitorList = visitorApi.findVisitorListByCount(UserHolder.getUserId(), 5);
        }
        //把本次记录时间 缓存到redis里
        redisTemplate.opsForValue().set("vistor_time_"+user.getId(),String.valueOf(System.currentTimeMillis()));

        //转换成vo
        List<VisitorVO> voList = new ArrayList<>();
        for (Visitor visitor : visitorList) {
            VisitorVO vo = new VisitorVO();
            UserInfo userInfo = userInfoApi.findById(visitor.getVisitorUserId());
            BeanUtils.copyProperties(userInfo,vo);
            voList.add(vo);
        }
        return ResponseEntity.ok(voList);


    }
}
